using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Xml;

namespace PT.Common
{
    /// <summary>
    /// XML配置文件操作类
    /// 提供XML配置文件的读取、写入和修改功能
    /// </summary>
    public class XmlConfig
    {
        private string xmlPath = "";
        private bool isConfig;
        private XmlDocument xmlDoc;

        /// <summary>
        /// 构造函数：装载配置文件
        /// </summary>
        /// <param name="xmlPath">配置文件的路径</param>
        public XmlConfig(string xmlPath)
        {
            this.XmlPath = xmlPath;
        }

        /// <summary>
        /// XML配置文件路径
        /// </summary>
        /// <value>配置文件的完整路径</value>
        public string XmlPath
        {
            set
            {
                xmlPath = value;
                isConfig = OnXmlPathChanged();
            }
        }

        /// <summary>
        /// 读取XML中的配置
        /// </summary>
        /// <param name="xpath">XPath查询路径</param>
        /// <param name="value">返回的节点值</param>
        /// <returns>读取是否成功</returns>
        public bool ReadConfig(string xpath, ref string value)
        {
            bool isRead = false;
            try
            {
                if (isConfig)
                {
                    XmlNode node = xmlDoc.SelectSingleNode(xpath);
                    if (node != null)
                    {
                        value = node.InnerText;
                        isRead = true;
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.Print(ex.Message);
            }
            return isRead;
        }

        /// <summary>
        /// 读取节点下的所有子节点键值对
        /// </summary>
        /// <param name="parentXpath">父节点XPath</param>
        /// <param name="myHashtable">用于存储读取结果的哈希表</param>
        /// <returns>读取是否成功</returns>
        public bool ReadConfigList(string parentXpath, ref Hashtable myHashtable)
        {
            bool isRead = false;
            try
            {
                if (isConfig)
                {
                    XmlNodeList nodes = xmlDoc.SelectNodes(parentXpath + "/*");
                    if (nodes != null)
                    {
                        foreach (XmlNode node in nodes)
                        {
                            if (node.Name != null && node.InnerText != null)
                            {
                                myHashtable.Add(node.Name, node.InnerText);
                            }
                        }
                        isRead = true;
                    }
                }
            }
            catch (Exception ex)
            {
                isRead = false;
                Debug.Print(ex.Message);
            }
            return isRead;
        }

        /// <summary>
        /// 向XML中写入配置
        /// </summary>
        /// <param name="xpath">XPath查询路径</param>
        /// <param name="value">要写入的节点值</param>
        /// <returns>写入是否成功</returns>
        /// <remarks>
        /// 该方法会更新现有节点的值，如果节点不存在则不会创建新节点
        /// 修改后会立即保存到文件
        /// </remarks>
        public bool WriteConfig(string xpath, string value)
        {
            bool isWrite = false;
            try
            {
                if (isConfig)
                {
                    XmlNode node = xmlDoc.SelectSingleNode(xpath);
                    if (node != null)
                    {
                        node.InnerText = value;
                        isWrite = SaveXml();
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.Print(ex.Message);
            }
            return isWrite;
        }

        #region 私有方法
        private bool OnXmlPathChanged()
        {
            bool isLoad = false;
            try
            {
                if (File.Exists(xmlPath))
                {
                    isLoad = LoadXml();
                }
            }
            catch (Exception ex)
            {
                Debug.Print(ex.Message);
            }
            return isLoad;
        }

        /// <summary>
        /// 从文件中加载XML配置信息
        /// </summary>
        /// <returns>加载是否成功</returns>
        private bool LoadXml()
        {
            bool isLoad = false;
            try
            {
                xmlDoc = new XmlDocument();
                xmlDoc.Load(xmlPath);
                isLoad = true;
            }
            catch (Exception ex)
            {
                Debug.Print(ex.Message);
            }
            return isLoad;
        }

        /// <summary>
        /// 将XML文档保存到文件
        /// </summary>
        /// <returns>保存是否成功</returns>
        private bool SaveXml()
        {
            bool isSave = false;
            try
            {
                xmlDoc.Save(xmlPath);
                isSave = true;
            }
            catch (Exception ex)
            {
                Debug.Print(ex.Message);
            }
            return isSave;
        }


        private void Test()
        {
            // 读取XML配置
            XmlConfig xmlConfig = new XmlConfig("config.xml");
            string value = "";
            if (xmlConfig.ReadConfig("/configuration/appSettings/add[@key='Timeout']/@value", ref value))
            {
                Console.WriteLine("Timeout: " + value);
            }

            // 写入XML配置
            xmlConfig.WriteConfig("/configuration/appSettings/add[@key='Timeout']/@value", "30");

            // 读取节点列表
            Hashtable settings = new Hashtable();
            if (xmlConfig.ReadConfigList("/configuration/appSettings", ref settings))
            {
                foreach (DictionaryEntry entry in settings)
                {
                    Console.WriteLine($"{entry.Key}: {entry.Value}");
                }
            }
        }
        #endregion
    }
}